package com.saa.common.redis.service;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Service
public class RedisService {

    private Logger LOGGER = LoggerFactory.getLogger(this.getClass());

	@Autowired
	private RedisTemplate<Object, Object> redisTemplate;
    //@Autowired
    //private ConfigdefineService configService;
	/**
	 * 功能描述：删除缓存redisData里面所有的内容(注：后期可以按缓存位置来清除)
	 * @author wangqian 2017-7-26
	 * 
	 */
	@CacheEvict(value = "redisData",allEntries=true)
	public String deleteCache(){
		//LogUtil.printLog("-------RedisService----deleteCache----------缓存清空完成---------");
		return "success";
	}
	/**
	 * 功能描述：删除缓存redisData里面所有的内容(注：后期可以按缓存位置来清除)
	 * @author wangqian 2017-7-26
	 * 
	 */
	@CacheEvict(value = "saaRedisData",allEntries=true)
	public String deleteCacheSaa(){
		//LogUtil.printLog("-------RedisService----deleteSaaCache----------缓存清空完成---------");
		return "success";
	}

    /**
     * 功能描述：redis初始化
     * @author dukedi 2018-7-13
     *
     */

    /*public String initRedisData(){
        RestTemplate restTemplate = RestTemplateUtil.getRestTemplate();
        String url = configService.queryByConfigCode("REDISINIT_URL");
        String result = null;
        try {
            result = restTemplate.getForEntity(url,String.class).getBody();
            LogUtil.printLog("-------RedisService----initRedis----------redis初始化完成---------");
        } catch (Exception e) {
            throw new BusinessException("redis初始化异常", false);
        }
        return result;
     }*/
    /**
     * 功能描述：es初始化
     * @author dukedi 2018-7-13
     *
     */

    /*public String initEsData(){
        String url = configService.queryByConfigCode("ESINIT_URL");
        RestTemplate restTemplate = RestTemplateUtil.getRestTemplate();
        String result = null;
        try {
            //result = restTemplate.postForObject(url, null, String.class);
            LOGGER.info("ES初始化响应报文:{}", JsonUtil.toPrettyJsonString(result));
            LogUtil.printLog("-------RedisService----initES----------ES初始化完成---------");
        } catch (Exception e) {
            throw new BusinessException("ES初始化异常",false);
        }
        return result;
    }*/
	/**
	 * 写入缓冲
	 * @param key
	 * @param value
	 * @return
	 */
	
	public boolean set(final String key,Object value){
		boolean result = false;
		try {
			ValueOperations<Object, Object> operations = redisTemplate.opsForValue();
			operations.set(key, value);
			result = true;
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		return result;
	}
	/**
	 * 写入缓冲设置时效时间
	 * @param key
	 * @param value
	 * @param expireTime
	 * @return
	 */
	public boolean set(final String key,Object value,Long expireTime){
		boolean result = false;
		try {
			ValueOperations<Object, Object> operations = redisTemplate.opsForValue();
			operations.set(key, value);
			redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
			result = true;
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		return result;
	}
	/**
     * 批量删除对应的value
     * @param keys
     */
    public void remove(final String... keys) {
        for (String key : keys) {
            remove(key);
        }
    }

    /**
     * 批量删除key
     * @param pattern
     */
    public void removePattern(final String pattern) {
        Set<Object> keys = redisTemplate.keys(pattern);
        if (keys.size() > 0){
            redisTemplate.delete(keys);
        }
    }
    /**
     * 删除对应的value
     * @param key
     */
    public void remove(final String key) {
        if (exists(key)) {
            redisTemplate.delete(key);
        }
    }
    /**
     * 判断缓存中是否有对应的value
     * @param key
     * @return
     */
    public boolean exists(final String key) {
        return redisTemplate.hasKey(key);
    }
    /**
     * 读取缓存
     * @param key
     * @return
     */
    public Object get(String key) {
        Object result = null;
        ValueOperations<Object, Object> operations = redisTemplate.opsForValue();
        result = operations.get(key);
        return result;
    }
    /**
     * 读取缓存
     * @param key
     * @return
     */
    public Object getC(String key) {
        Object result = null;
        ValueOperations<Object, Object> operations = redisTemplate.opsForValue();
        result = operations.get(key);
        return result;
    }
    /**
     * 哈希 添加
     * @param key
     * @param hashKey
     * @param value
     */
    public void hmSet(String key, Object hashKey, Object value){
        HashOperations<Object, Object, Object>  hash = redisTemplate.opsForHash();
        hash.put(key,hashKey,value);
    }

    /**
     * 哈希 删除
     * @param key
     * @param hashKey
     */
    public void removeHSet(String key, Object hashKey){
        HashOperations<Object, Object, Object>  hash = redisTemplate.opsForHash();
        hash.delete(key,hashKey);
    }

    /**
     * 哈希 大小
     * @param key
     */
    public long hSize(String key){
        HashOperations<Object, Object, Object>  hash = redisTemplate.opsForHash();
        return hash.size(key);
    }

    /**
     * 哈希 entry
     * @param key
     */
    public Map<Object,Object> hEntry(String key){
        HashOperations<Object, Object, Object>  hash = redisTemplate.opsForHash();
        return hash.entries(key);
    }

    /**
     * 哈希获取数据
     * @param key
     * @param hashKey
     * @return
     */
    public Object hmGet(String key, Object hashKey){
        HashOperations<Object, Object, Object>  hash = redisTemplate.opsForHash();
        return hash.get(key,hashKey);
    }

    /**
     * 列表添加
     * @param k
     * @param v
     */
    public void lPush(String k,Object v){
        ListOperations<Object, Object> list = redisTemplate.opsForList();
        list.rightPush(k,v);
    }

    /**
     * 列表获取
     * @param k
     * @param l
     * @param l1
     * @return
     */
    public List<Object> lRange(String k, long l, long l1){
        ListOperations<Object, Object> list = redisTemplate.opsForList();
        return list.range(k,l,l1);
    }

    /**
     * 集合添加
     * @param key
     * @param value
     */
    public void add(String key,Object value){
        SetOperations<Object, Object> set = redisTemplate.opsForSet();
        set.add(key,value);
    }

    /**
     * 集合获取
     * @param key
     * @return
     */
    public Set<Object> setMembers(String key){
        SetOperations<Object, Object> set = redisTemplate.opsForSet();
        return set.members(key);
    }

    /**
     * 有序集合添加
     * @param key
     * @param value
     * @param score
     */
    public void zAdd(String key,Object value,double score){
        ZSetOperations<Object, Object> zset = redisTemplate.opsForZSet();
        zset.add(key,value, score);
    }

    /**
     * 有序集合删除
     * @param key
     * @param value
     */
    public void zRemove(String key,Object value){
        ZSetOperations<Object, Object> zset = redisTemplate.opsForZSet();
        zset.remove(key,value);
    }

    /**
     * 有序集合大小
     * @param key
     */
    public long zSize(String key){
        ZSetOperations<Object, Object> zset = redisTemplate.opsForZSet();
        return zset.size(key);
    }

    /**
     * 有序集合获取 顺序
     * @param key
     * @param min
     * @param max
     * @return
     */
    public Set<Object> rangeByScore(String key, double min, double max){
        ZSetOperations<Object, Object> zset = redisTemplate.opsForZSet();
        return zset.rangeByScore(key, min, max);
    }

    /**
     * 有序集合获取 逆序
     * @param key
     * @param min
     * @param max
     * @return
     */
    public Set<Object> reverseRangeByScore(String key, double min, double max){
        ZSetOperations<Object, Object> zset = redisTemplate.opsForZSet();
        return zset.reverseRangeByScore(key, min, max);
    }

    /**
     * 获取分布式锁
     */
    public boolean getDistributeLock(String lockKey,Long timeOut){
        boolean result;
        try {
            ValueOperations<Object, Object> operations = redisTemplate.opsForValue();
            result = operations.setIfAbsent(lockKey,lockKey);
            redisTemplate.expire(lockKey,timeOut,TimeUnit.SECONDS);
            if (result){
                LOGGER.info("已获取到 {} 对应的锁!",lockKey);
            }else{
                LOGGER.info("未获取到{}任务执行锁,锁已被集群中其他服务获取！",lockKey);
            }
        } catch (Exception e) {
            //LOGGER.error("Redis操作异常!\n" + CommonUtil.getStackTrace(e));
            result = true;
        }
        return result;
    }

    /**
     * 释放分布式锁
     */
    public boolean releaseDistributeLock(String lockKey){
        boolean result;
        try {
            redisTemplate.delete(lockKey);
            result = true;
        } catch (Exception e) {
            //LOGGER.error("Redis操作异常!\n" + CommonUtil.getStackTrace(e));
            result = false;
        }
        return result;
    }

    /**
     * 获取分布式锁（主要用于mq消费）
     *
     * @param timeout        获取的超时时间(在这个超时时间内多次请求)
     * @param tryInterval    多少ms尝试一次
     * @param lockExpireTime 获取成功后锁的过期时间
     * @return true 获取成功，false获取失败
     */
    public boolean getDistributeLockMQ(String lockKey, Long timeout, Long tryInterval, Long lockExpireTime){
        boolean result;
        try {
        	/*if (CommonUtil.isNullString(lockKey)) {
                return false;
            }*/
            long startTime = System.currentTimeMillis();
            long continuedTime = 0L;
            do {
                ValueOperations<Object, Object> operations = redisTemplate.opsForValue();
                result = operations.setIfAbsent(lockKey,lockKey);
                LOGGER.info("查看redisTemplate锁是否设置成功!"+redisTemplate.getExpire(lockKey));
                if (result){
                    LOGGER.info("已获取到 {} 对应的锁!",lockKey);
                    redisTemplate.expire(lockKey,lockExpireTime,TimeUnit.MILLISECONDS);
                    return result;
                }else{
                    LOGGER.info("未获取到{}任务执行锁,锁已被集群中其他服务获取！",lockKey);
				}
				// 尝试超过了设定值之后直接跳出循环
				continuedTime = System.currentTimeMillis() - startTime;
				Thread.sleep(tryInterval);
            } while (continuedTime <= timeout);
        } catch (Exception e) {
            //LOGGER.error("Redis操作异常!\n" + CommonUtil.getStackTrace(e));
            result = false;
        }
        return result;
    }
}
